/*
 * 描          述:  <描述>
 * 修  改   人:  
 * 修改时间:  
 * <修改描述:>
 */
package com.tx.component.task.service.impl;

import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.Column;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.transaction.annotation.Transactional;

import com.tx.component.task.dao.TaskDefDao;
import com.tx.component.task.model.TaskDef;
import com.tx.component.task.service.TaskDefService;
import com.tx.core.exceptions.util.AssertUtils;
import com.tx.core.paged.model.PagedList;
import com.tx.core.querier.model.Filter;
import com.tx.core.querier.model.Querier;
import com.tx.core.querier.model.QuerierBuilder;

/**
 * TaskDef的业务层
 * <功能详细描述>
 * 
 * @author  
 * @version  [版本号, ]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class TaskDefServiceImpl implements TaskDefService {
    
    @SuppressWarnings("unused")
    private Logger logger = LoggerFactory.getLogger(TaskDefServiceImpl.class);
    
    /** 模块 */
    private String module;
    
    /** 任务定义持久层 */
    private TaskDefDao taskDefDao;
    
    /** <默认构造函数> */
    public TaskDefServiceImpl() {
        super();
    }
    
    /** <默认构造函数> */
    public TaskDefServiceImpl(String module, TaskDefDao taskDefDao) {
        super();
        this.module = module;
        this.taskDefDao = taskDefDao;
    }
    
    /**
     * @param task
     */
    @Override
    @Transactional
    public void save(TaskDef task) {
        AssertUtils.notNull(task, "task is null");
        
        String taskId = task.getId();
        TaskDef hisTask = findById(taskId);
        if (hisTask == null) {
            //插入任务定义
            insert(task);
        } else {
            if (!StringUtils.equals(task.getParentId(), hisTask.getParentId())
                    || !StringUtils.equals(task.getName(), hisTask.getName())
                    || !StringUtils.equals(task.getBeanName(),
                            hisTask.getBeanName())
                    || !StringUtils.equals(task.getClassName(),
                            hisTask.getClassName())
                    || !StringUtils.equals(task.getMethodName(),
                            hisTask.getMethodName())
                    || !StringUtils.equals(task.getRemark(),
                            hisTask.getRemark())
                    || !StringUtils.equals(task.getParameters(),
                            hisTask.getParameters())
                    || task.getPriority() != hisTask.getPriority()
                    || task.isExecutable() != hisTask.isExecutable()) {
                //如果内容存在不同，则对相关信息进行更新
                updateById(hisTask.getId(), task);
            }
        }
    }
    
    /**
     * @param taskDef
     */
    @Override
    @Transactional
    public void insert(TaskDef taskDef) {
        //验证参数是否合法
        AssertUtils.notNull(taskDef, "taskDef is null.");
        
        //为添加的数据需要填入默认值的字段填入默认值
        Date now = new Date();
        taskDef.setCreateDate(now);
        taskDef.setLastUpdateDate(now);
        taskDef.setModule(this.module);
        
        //调用数据持久层对实体进行持久化操作
        this.taskDefDao.insert(taskDef);
    }
    
    /**
     * @param id
     * @return
     */
    @Override
    @Transactional
    public boolean deleteById(String id) {
        AssertUtils.notEmpty(id, "id is empty.");
        
        TaskDef condition = new TaskDef();
        condition.setId(id);
        int resInt = this.taskDefDao.delete(condition);
        
        boolean flag = resInt > 0;
        return flag;
    }
    
    /**
     * @param id
     * @return
     */
    @Override
    public TaskDef findById(String id) {
        AssertUtils.notEmpty(id, "id is empty.");
        
        TaskDef condition = new TaskDef();
        condition.setId(id);
        
        TaskDef res = this.taskDefDao.find(condition);
        return res;
    }
    
    /**
     * @param id
     * @return
     */
    @Override
    @Transactional
    public TaskDef findWithLockById(String id) {
        AssertUtils.notEmpty(id, "id is empty.");
        
        TaskDef condition = new TaskDef();
        condition.setId(id);
        
        TaskDef res = this.taskDefDao.findWithLock(condition);
        return res;
    }
    
    /**
     * @param valid
     * @param params
     * @return
     */
    @Override
    public List<TaskDef> queryList(Boolean valid, Map<String, Object> params) {
        //生成查询条件
        params = params == null ? new HashMap<String, Object>() : params;
        params.put("valid", valid);
        params.put("module", this.module);
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        List<TaskDef> resList = this.taskDefDao.queryList(params);
        
        return resList;
    }
    
    /**
     * @param valid
     * @param querier
     * @return
     */
    @Override
    public List<TaskDef> queryList(Boolean valid, Querier querier) {
        //生成查询条件
        querier = querier == null ? QuerierBuilder.newInstance().querier()
                : querier;
        if (valid != null) {
            querier.getFilters().add(Filter.eq("valid", valid));
            querier.getFilters().add(Filter.eq("module", this.module));
        }
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        List<TaskDef> resList = this.taskDefDao.queryList(querier);
        
        return resList;
    }
    
    /**
     * @param valid
     * @param params
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @Override
    public PagedList<TaskDef> queryPagedList(Boolean valid,
            Map<String, Object> params, int pageIndex, int pageSize) {
        //生成查询条件
        params = params == null ? new HashMap<String, Object>() : params;
        params.put("valid", valid);
        params.put("module", this.module);
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        PagedList<TaskDef> resPagedList = this.taskDefDao
                .queryPagedList(params, pageIndex, pageSize);
        
        return resPagedList;
    }
    
    /**
     * @param valid
     * @param querier
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @Override
    public PagedList<TaskDef> queryPagedList(Boolean valid, Querier querier,
            int pageIndex, int pageSize) {
        //生成查询条件
        querier = querier == null ? QuerierBuilder.newInstance().querier()
                : querier;
        if (valid != null) {
            querier.getFilters().add(Filter.eq("valid", valid));
            querier.getFilters().add(Filter.eq("module", this.module));
        }
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        PagedList<TaskDef> resPagedList = this.taskDefDao
                .queryPagedList(querier, pageIndex, pageSize);
        
        return resPagedList;
    }
    
    /**
     * @param valid
     * @param params
     * @return
     */
    @Override
    public int count(Boolean valid, Map<String, Object> params) {
        //生成查询条件
        params = params == null ? new HashMap<String, Object>() : params;
        params.put("valid", valid);
        params.put("module", this.module);
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        int res = this.taskDefDao.count(params);
        
        return res;
    }
    
    /**
     * @param valid
     * @param querier
     * @return
     */
    @Override
    public int count(Boolean valid, Querier querier) {
        //生成查询条件
        querier = querier == null ? QuerierBuilder.newInstance().querier()
                : querier;
        if (valid != null) {
            querier.getFilters().add(Filter.eq("valid", valid));
            querier.getFilters().add(Filter.eq("module", this.module));
        }
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        int res = this.taskDefDao.count(querier);
        
        return res;
    }
    
    /**
     * @param key2valueMap
     * @param excludeId
     * @return
     */
    @Override
    public boolean exists(Map<String, String> key2valueMap, String excludeId) {
        AssertUtils.notEmpty(key2valueMap, "key2valueMap is empty");
        
        //生成查询条件
        Map<String, Object> params = new HashMap<String, Object>();
        params.putAll(key2valueMap);
        params.put("module", this.module);
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        int res = this.taskDefDao.count(params, excludeId);
        
        return res > 0;
    }
    
    /**
     * @param querier
     * @param excludeId
     * @return
     */
    @Override
    public boolean exists(Querier querier, String excludeId) {
        AssertUtils.notNull(querier, "querier is null.");
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        querier.getFilters().add(Filter.eq("module", this.module));
        int res = this.taskDefDao.count(querier, excludeId);
        
        return res > 0;
    }
    
    /**
     * @param id
     * @param updateRowMap
     * @return
     */
    @Override
    @Transactional
    public boolean updateById(String id, Map<String, Object> updateRowMap) {
        //验证参数是否合法，必填字段是否填写
        AssertUtils.notEmpty(id, "id is empty.");
        AssertUtils.notEmpty(updateRowMap, "updateRowMap is empty.");
        
        updateRowMap.put("lastUpdateDate", new Date());
        boolean flag = this.taskDefDao.update(id, updateRowMap);
        //如果需要大于1时，抛出异常并回滚，需要在这里修改
        return flag;
    }
    
    /**
     * @param id
     * @param taskDef
     * @return
     */
    @Override
    @Transactional
    public boolean updateById(String id, TaskDef taskDef) {
        //验证参数是否合法，必填字段是否填写
        AssertUtils.notNull(taskDef, "taskDef is null.");
        AssertUtils.notEmpty(id, "id is empty.");
        AssertUtils.notEmpty(taskDef.getModule(), "taskDef.module is empty.");
        
        //生成需要更新字段的hashMap
        Map<String, Object> updateRowMap = new HashMap<String, Object>();
        //需要更新的字段
        //updateRowMap.put("module", taskDef.getModule());
        updateRowMap.put("beanName", taskDef.getBeanName());
        updateRowMap.put("className", taskDef.getClassName());
        updateRowMap.put("methodName", taskDef.getMethodName());
        
        updateRowMap.put("name", taskDef.getName());
        updateRowMap.put("parentId", taskDef.getParentId());
        updateRowMap.put("priority", taskDef.getPriority());
        updateRowMap.put("executable", taskDef.isExecutable());
        updateRowMap.put("remark", taskDef.getRemark());
        updateRowMap.put("parameters", taskDef.getParameters());
        
        updateRowMap.put("lastUpdateDate", new Date());
        
        boolean flag = this.taskDefDao.update(id, updateRowMap);
        //如果需要大于1时，抛出异常并回滚，需要在这里修改
        return flag;
    }
    
    /**
     * @param taskDef
     * @return
     */
    @Override
    @Transactional
    public boolean updateById(TaskDef taskDef) {
        //验证参数是否合法，必填字段是否填写
        AssertUtils.notNull(taskDef, "taskDef is null.");
        AssertUtils.notEmpty(taskDef.getId(), "taskDef.id is empty.");
        
        Map<String, Object> updateRowMap = new HashMap<String, Object>();
        BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(taskDef);
        for (PropertyDescriptor pd : bw.getPropertyDescriptors()) {
            if (pd.getWriteMethod() == null || pd.getReadMethod() == null) {
                continue;
            }
            if ("id".equals(pd.getName())) {
                continue;
            }
            TypeDescriptor td1 = bw.getPropertyTypeDescriptor(pd.getName());
            if (td1.hasAnnotation(Column.class)
                    && !td1.getAnnotation(Column.class).updatable()) {
                continue;
            }
            updateRowMap.put(pd.getName(), bw.getPropertyValue(pd.getName()));
        }
        boolean flag = updateById(taskDef.getId(), updateRowMap);
        //如果需要大于1时，抛出异常并回滚，需要在这里修改
        return flag;
    }
    
    /**
     * @param id
     * @return
     */
    @Override
    @Transactional
    public boolean disableById(String id) {
        AssertUtils.notEmpty(id, "id is empty.");
        
        //生成条件
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("id", id);
        params.put("valid", false);
        params.put("lastUpdateDate", new Date());
        
        boolean flag = this.taskDefDao.update(params) > 0;
        
        return flag;
    }
    
    /**
     * @param id
     * @return
     */
    @Override
    @Transactional
    public boolean enableById(String id) {
        AssertUtils.notEmpty(id, "id is empty.");
        
        //生成查询条件
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("id", id);
        params.put("valid", true);
        params.put("lastUpdateDate", new Date());
        
        boolean flag = this.taskDefDao.update(params) > 0;
        
        return flag;
    }
    
    /**
     * @param parentId
     * @param valid
     * @param params
     * @return
     */
    @Override
    public List<TaskDef> queryChildrenByParentId(String parentId, Boolean valid,
            Map<String, Object> params) {
        //判断条件合法性
        AssertUtils.notEmpty(parentId, "parentId is empty.");
        
        //生成查询条件
        params = params == null ? new HashMap<String, Object>() : params;
        params.put("parentId", parentId);
        params.put("valid", valid);
        params.put("module", this.module);
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        List<TaskDef> resList = this.taskDefDao.queryList(params);
        
        return resList;
    }
    
    /**
     * @param parentId
     * @param valid
     * @param querier
     * @return
     */
    @Override
    public List<TaskDef> queryChildrenByParentId(String parentId, Boolean valid,
            Querier querier) {
        //判断条件合法性
        AssertUtils.notEmpty(parentId, "parentId is empty.");
        
        //生成查询条件
        querier = querier == null ? QuerierBuilder.newInstance().querier()
                : querier;
        if (valid != null) {
            querier.getFilters().add(Filter.eq("valid", valid));
            querier.getFilters().add(Filter.eq("module", this.module));
        }
        querier.getFilters().add(Filter.eq("parentId", parentId));
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        List<TaskDef> resList = this.taskDefDao.queryList(querier);
        
        return resList;
    }
    
    /**
     * @param parentId
     * @param valid
     * @param params
     * @return
     */
    @Override
    public List<TaskDef> queryDescendantsByParentId(String parentId,
            Boolean valid, Map<String, Object> params) {
        //判断条件合法性
        AssertUtils.notEmpty(parentId, "parentId is empty.");
        
        //生成查询条件
        params = params == null ? new HashMap<String, Object>() : params;
        params.put("module", this.module);
        Set<String> ids = new HashSet<>();
        Set<String> parentIds = new HashSet<>();
        parentIds.add(parentId);
        
        List<TaskDef> resList = doNestedQueryChildren(valid,
                ids,
                parentIds,
                params);
        return resList;
    }
    
    /**
     * 查询嵌套列表<br/>
     * <功能详细描述>
     * @param ids
     * @param parentIds
     * @param params
     * @return [参数说明]
     * 
     * @return List<TaskDef> [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    private List<TaskDef> doNestedQueryChildren(Boolean valid, Set<String> ids,
            Set<String> parentIds, Map<String, Object> params) {
        if (CollectionUtils.isEmpty(parentIds)) {
            return new ArrayList<TaskDef>();
        }
        
        //ids避免数据出错时导致无限循环
        Map<String, Object> queryParams = new HashMap<>();
        queryParams.putAll(params);
        queryParams.put("parentIds", parentIds);
        List<TaskDef> resList = queryList(valid, queryParams);
        
        Set<String> newParentIds = new HashSet<>();
        for (TaskDef bdTemp : resList) {
            if (!ids.contains(bdTemp.getId())) {
                newParentIds.add(bdTemp.getId());
            }
            ids.add(bdTemp.getId());
        }
        //嵌套查询下一层级
        resList.addAll(doNestedQueryChildren(valid, ids, newParentIds, params));
        return resList;
    }
    
    /**
     * @param parentId
     * @param valid
     * @param querier
     * @return
     */
    @Override
    public List<TaskDef> queryDescendantsByParentId(String parentId,
            Boolean valid, Querier querier) {
        //判断条件合法性
        AssertUtils.notEmpty(parentId, "parentId is empty.");
        
        //生成查询条件
        querier = querier == null ? QuerierBuilder.newInstance().querier()
                : querier;
        querier.getFilters().add(Filter.eq("module", this.module));
        Set<String> ids = new HashSet<>();
        Set<String> parentIds = new HashSet<>();
        parentIds.add(parentId);
        
        List<TaskDef> resList = doNestedQueryChildren(valid,
                ids,
                parentIds,
                querier);
        return resList;
    }
    
    /**
     * 嵌套查询列表<br/>
     * <功能详细描述>
     * @param ids
     * @param parentIds
     * @param querier
     * @return [参数说明]
     * 
     * @return List<TaskDef> [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    private List<TaskDef> doNestedQueryChildren(Boolean valid, Set<String> ids,
            Set<String> parentIds, Querier querier) {
        if (CollectionUtils.isEmpty(parentIds)) {
            return new ArrayList<TaskDef>();
        }
        
        //ids避免数据出错时导致无限循环
        Querier querierClone = (Querier) querier.clone();
        querierClone.getFilters().add(Filter.in("parentId", parentIds));
        List<TaskDef> resList = queryList(valid, querierClone);
        
        Set<String> newParentIds = new HashSet<>();
        for (TaskDef bdTemp : resList) {
            if (!ids.contains(bdTemp.getId())) {
                newParentIds.add(bdTemp.getId());
            }
            ids.add(bdTemp.getId());
        }
        //嵌套查询下一层级
        resList.addAll(
                doNestedQueryChildren(valid, ids, newParentIds, querier));
        return resList;
    }
    
    /**
     * @param 对module进行赋值
     */
    public void setModule(String module) {
        this.module = module;
    }
    
    /**
     * @param 对taskDefDao进行赋值
     */
    public void setTaskDefDao(TaskDefDao taskDefDao) {
        this.taskDefDao = taskDefDao;
    }
    
}
